home *** CD-ROM | disk | FTP | other *** search
- #include <Events.h>
- #include <Resources.h>
- #include <Memory.h>
- #include <ToolUtils.h>
- #include <Gestalt.h>
- #include <Errors.h>
-
- #include "Beeper.h"
-
- // some sane defaults in case we can't find our prefs.
- BeeperGlobals gBeeperGlobs = {
- 0,
- 0,
- "\p",
- "\p",
- "\p",
- "\p",
- "\p"
- };
-
- pascal short (*gOldSystemEvent)(EventRecord *theEvent);
-
- pascal short BeeperSystemEvent(EventRecord *theEvent);
-
- enum {
- uppSystemEventProcInfo = kPascalStackBased | RESULT_SIZE(kTwoByteCode) | STACK_ROUTINE_PARAMETER(1, kFourByteCode)
- };
-
- SelectorFunctionUPP ourGestaltUPP;
-
- static pascal OSErr BeeperGestalt(OSType selector, long *_response);
-
- #ifdef powerc
- // for Metrowerks' linker, this defines the interface for main().
- ProcInfoType __procinfo = kCStackBased | RESULT_SIZE(kNoByteCode);
- #endif
-
- void main(void)
- {
- long oldA4;
- THz oldZone;
- // BeeperGlobals **bgh;
- UniversalProcPtr newSystemEventAddress;
-
- // Set up A4, so we can access our globals.
- oldA4 = SetCurrentA4();
-
- // Set the current zone to the system zone. In the 680x0 case, this
- // is not necessary, but it's not a bad idea and it keeps us out of
- // trouble when traps that we don't expect to have side effects
- // unexpectedlty allocate memory from the current zone. One example
- // of this is the NewRoutineDescriptor routine.
- oldZone = GetZone();
- SetZone(SystemZone());
-
- // OK, we're relying on gestalt, so we have to be sure that it's
- // implemented. We do this by checking to see that Gestalt's trap
- // address is different from the address of unimplemented traps.
- if (GetOSTrapAddress(kGestaltTrapNumber) == UnimplementedTrapAddress) goto initFailed;
-
- ourGestaltUPP = NewSelectorFunctionProc(BeeperGestalt);
- if (ourGestaltUPP == 0) goto initFailed;
-
- newSystemEventAddress = NewRoutineDescriptor((ProcPtr) &BeeperSystemEvent,uppSystemEventProcInfo,GetCurrentISA());
- if (newSystemEventAddress == 0) goto initFailed;
-
- // now install our gestalt selector, which sets up a mechanism for our control panel
- // to talk to us and at the same time makes sure we're not loading twice.
- if (NewGestalt(kDTS_Signature, ourGestaltUPP) != noErr) goto initFailed;
-
- // At this point, we have tested for any failure conditions, and nothing has gone wrong.
- // So now is the time to detach our code, patch our traps, and settle in.
- DetachResource(GetResource('INIT', -4048));
-
- // Remember the old implementation of SystemEvent.
- gOldSystemEvent = (void *) GetToolTrapAddress(kSystemEventTrapNumber);
-
- // Patch ourselves in.
- SetToolTrapAddress(newSystemEventAddress, kSystemEventTrapNumber);
-
- // bgh = (BeeperGlobals **)Get1Resource('pref', -4048);
- // if (bgh != 0 && GetHandleSize((Handle)bgh) == sizeof(gBeeperGlobs)) {
- // gBeeperGlobs = **bgh;
- // }
-
- initFailed:
- // Restore the old zone again
- SetZone(oldZone);
-
- // And restore the value of A4 on the way out.
- SetA4(oldA4);
- }
-
- static pascal OSErr BeeperGestalt(OSType selector, long *response) {
- long oldA4;
- OSErr err = noErr;
-
- // Set up A4, so we can access our globals.
- oldA4 = SetCurrentA4();
-
- switch (selector) {
- case kGestaltGetInitGlobals:
- *response = (long)&gBeeperGlobs;
- break;
- case kDTS_Signature:
- *response = (long)ourGestaltUPP;
- break;
- case gestaltVersion:
- *response = 0x0100; // version 1.0 Gestalt interface for Beeper.
- break;
- default:
- err = gestaltUnknownErr;
- break;
- }
-
- // Restore the value of A4 on the way out.
- SetA4(oldA4);
- return err;
- }
-
- static void HandleKeyDown(short modifiers, long eventMessage);
-
- pascal short BeeperSystemEvent(EventRecord *theEvent)
- {
- // Set up A4, so we can access our globals.
- long oldA4;
- short result;
-
- oldA4 = SetCurrentA4();
-
- // Check for keyDown events, and pass them to HandleKeyDown:
- if (theEvent->what == keyDown) {
- HandleKeyDown(theEvent->modifiers, theEvent->message);
- }
-
- // Call the old SystemEvent:
- #ifndef powerc
- result = gOldSystemEvent(theEvent);
- #else
- result = CallUniversalProc((UniversalProcPtr)gOldSystemEvent, uppSystemEventProcInfo, theEvent);
- #endif
- // And restore the value of A4 on the way out.
- SetA4(oldA4);
-
- return result;
- }
-
- enum { kMaxKeysRecorded = sizeof(gBeeperGlobs.asBuf[0]) };
-
- uchar gLastKeys[kMaxKeysRecorded + 1];
-
- static void HandleKeyDown(short modifiers, long eventMessage)
- {
- StringPtr lastkeys; // we keep the address of gLastKeys in a local variable ...
-
- lastkeys = gLastKeys; // ... because we access it so often
-
- // If the user types command-O or command-V, or command-Anything,
- // our buffer is probably invalid, and we certainly shouldn't
- // record the keystroke!
- if (modifiers & cmdKey) {
- // lastkeys[0] = 0;
- return;
- }
-
- // if it's a backspace, back up over one of our recorded keys.
- if ('\b' == (char)eventMessage) {
- if (lastkeys[0] != 0) {
- lastkeys[0]--;
- }
- return;
- }
-
- // if it isn't, add the new key to the end of what we've recorded so far.
- // first, if we're about to overflow, throw away one old key.
- if (lastkeys[0] == kMaxKeysRecorded) {
- BlockMove(&lastkeys[2], &lastkeys[1], kMaxKeysRecorded - 1);
- lastkeys[0]--;
- }
-
- // then, store the new typed character:
- if (' ' == (char)eventMessage)
- {
- BlockMove(&lastkeys[0],&gBeeperGlobs.asBuf[gBeeperGlobs.lWriteBuf][0],lastkeys[0]+1);
- lastkeys[0] = 0;
- gBeeperGlobs.lWriteBuf++;
- if(gBeeperGlobs.lWriteBuf>4) gBeeperGlobs.lWriteBuf = 0;
-
- }
- else
- {
- lastkeys[0]++;
- lastkeys[lastkeys[0]] = eventMessage;
- }
-
- // have we accumulated "beep"?
- // if (lastkeys[0] == gBeeperGlobs.BeepString[0]) {
- // if (RelString(lastkeys, gBeeperGlobs.BeepString, false /* not case sens */, true /* diacritical sensitive */) == sortsEqual) {
- // SysBeep(8);
- // lastkeys[0] = 0;
- // }
- // }
- }
-
-